package com.traffic.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.sun.org.apache.xpath.internal.operations.Bool;
import com.traffic.annotation.ApiJsonObject;
import com.traffic.annotation.ApiJsonProperty;
import com.traffic.constant.Status;
import com.traffic.entity.Drivedata;
import com.traffic.entity.Param;
import com.traffic.entity.QueryResult;
import com.traffic.entity.Trajectory;

import com.traffic.exception.BaseException;
import com.traffic.model.ApiResponse;

import com.traffic.model.TrajectoryResult;
import com.traffic.service.BaidumapService;
import com.traffic.service.DrivedataService;
import com.traffic.service.RankService;
import com.traffic.service.TrajectoryService;
import com.traffic.util.BaidumapUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.util.*;

@Api(tags = "轨迹相关接口")
@RestController
@RequestMapping(value = "/trajectory")
@Slf4j
public class TrajectoryController {

    @Autowired
    TrajectoryService trajectoryService;

    @Autowired
    DrivedataService drivedataService;

    @Autowired
    RankService rankService;

    @Autowired
    BaidumapService baidumapService;

    @Autowired
    BaidumapUtil baidumapUtil;

    @ApiOperation(value = "【轨迹】", notes = "历史轨迹")
    @ApiImplicitParam(paramType = "path", dataType = "Integer", name = "userId", value = "用户id", required = true)
    @GetMapping("/history/{userId}/{points}")
    public ApiResponse historyTrajectory(@PathVariable Long userId,@PathVariable Integer points) {

        QueryWrapper<Trajectory> wrapper = new QueryWrapper<>();
        List<Trajectory> trajectorys= trajectoryService.list(wrapper.eq("user_id",userId).orderByDesc("start_time"));

        if (trajectorys.isEmpty()) {
            return ApiResponse.ofStatus(Status.OK);
        }else {
            List<TrajectoryResult> trajectoryResults = new ArrayList<>();
            for (Trajectory tr: trajectorys) {

                QueryWrapper<Drivedata> drivewrapper = new QueryWrapper<>();
                Drivedata drive = drivedataService.getOne(drivewrapper.eq("trail_id",tr.getId()));

                if (drive.getMileage()<2.0)continue;

                TrajectoryResult temp = new TrajectoryResult();
                if(points==0) tr.setPoints("");
                temp.setTrajectory(tr);
                Drivedata drivedata = drivedataService.getOne(new QueryWrapper<Drivedata>().eq("trail_id",tr.getId()));
                temp.setMileage(drivedata.getMileage());
                temp.setTime(drivedata.getTime());
                temp.setScore(drivedata.getScore());
                trajectoryResults.add(temp);
            }


            return ApiResponse.ofStatus(Status.OK, trajectoryResults);
        }
    }

    @ApiOperation(value = "【轨迹】", notes = "年月历史轨迹")
    @ApiImplicitParam(paramType = "path", dataType = "Integer", name = "yearmonth", value = "用户id", required = true)
    @GetMapping("/history/{userId}/{year}/{month}/{points}")
    public ApiResponse historyTrajectory(@PathVariable Long userId,
                                         @PathVariable  Integer year,
                                         @PathVariable  Integer month,
                                         @PathVariable Integer points) {

        final TimeZone timeZone = TimeZone.getTimeZone("Asia/Shanghai");
        TimeZone.setDefault(timeZone);
        String time1 = year+"-"+month+"-01";

        String time2;
        if(month<12){
            time2 = year+"-"+(month+1)+"-01";
        }else{
            time2 = year+"-"+month+"-31";
        }


        QueryWrapper<Trajectory> wrapper = new QueryWrapper<>();
        List<Trajectory> trajectorys= trajectoryService.list(wrapper.eq("combine",1).eq("user_id",userId).between("start_time",time1,time2).orderByDesc("start_time") );

        if (trajectorys.isEmpty()) {
            return ApiResponse.ofStatus(Status.OK);
        }else {
            List<TrajectoryResult> trajectoryResults = new ArrayList<>();
            for (Trajectory tr: trajectorys) {

                QueryWrapper<Drivedata> drivewrapper = new QueryWrapper<>();
                Drivedata drive = drivedataService.getOne(drivewrapper.eq("trail_id",tr.getId()));

                if (drive.getMileage()<2.0)continue;

                TrajectoryResult temp = new TrajectoryResult();
                if(points==0) tr.setPoints("");
                temp.setTrajectory(tr);
                Drivedata drivedata = drivedataService.getOne(new QueryWrapper<Drivedata>().eq("trail_id",tr.getId()));
                temp.setMileage(drivedata.getMileage());
                temp.setTime(drivedata.getTime());
                temp.setScore(drivedata.getScore());
                trajectoryResults.add(temp);
            }

            return ApiResponse.ofStatus(Status.OK, trajectoryResults);
        }
    }

    //
    @ApiOperation(value = "【轨迹】", notes = "新增轨迹")
    @GetMapping("/insert/{user_id}")

    public ApiResponse insertTrajectory(@PathVariable Long user_id) {

       Long insrertid = trajectoryService.insertTrajectory(user_id);

       Drivedata dr = Drivedata.builder().trailId(insrertid)
               .averageAcceleration(0.0).averageSpeed(0.0).createTime(new DateTime()).score(0.0)
               .maxNacceleration(0.0).maxSpeed(0.0).mileage(0.0).time(0.0)
               .stationarity(0.0).maxAcceleration(0.0).build();
       drivedataService.save(dr);


        return ApiResponse.ofStatus(Status.OK,insrertid);
    }


    @ApiOperation(value = "【轨迹】", notes = "更新当前轨迹")
    @PostMapping("/update")
    @ApiJsonObject(name = "trajectoryParam",value = {
            @ApiJsonProperty(type =Integer.class,key = "id",example = "1" , description = "轨迹id"),
            @ApiJsonProperty(type =Integer.class,key = "user_id",example = "1" , description = "用户id"),
            @ApiJsonProperty(type =String.class,key = "start_point",example = "118.23456,30.45687" , description = "起始点"),
            @ApiJsonProperty(type =String.class,key = "end_point",example = "118.63456,30.554557" , description = "结束点"),
            @ApiJsonProperty(type =String.class,key = "start_time",example = "2020-09-06 07:11:03" , description = "开始时间：YYYY-MM-dd HH:mm:ss"),
            @ApiJsonProperty(type =String.class,key = "end_time",example = "2020-09-06 07:30:25" , description = "结束时间：YYYY-MM-dd HH:mm:ss"),
            @ApiJsonProperty(type =String.class,key = "points",example = "111.33,23.33|112.33,23.33|113.22,24.22" , description = "轨迹点:x1,y1|x2,y2|x3,y3|x4,y4"),

    })
    public ApiResponse updateTrajectory(@RequestBody Map<String, Object> trajectoryParam) {

        trajectoryService.updateTrajectory(trajectoryParam);

        return ApiResponse.ofStatus(Status.OK);

    }

    //先发drivedata/update和trajectory/update再发end结束请求

    @ApiOperation(value = "【轨迹】", notes = "结束轨迹,先发drivedata/update和trajectory/update再发end结束请求")
    @ApiImplicitParam(paramType = "path", dataType = "Integer", name = "userId", value = "用户id,结束该用户的轨迹（包括以前意外退出未关闭的）", required = true)
    @GetMapping("/end/{userId}")
    public ApiResponse endTrajectory(@PathVariable Long userId) throws ParseException {


        QueryWrapper<Trajectory> wrapper = new QueryWrapper<>();
        List<Trajectory> tlist = trajectoryService.list(wrapper.eq("user_id",userId).eq("combine",0));

        List<Long> tr_ids = new ArrayList<>();

        for (Trajectory traj:tlist) {
            tr_ids.add(traj.getId());
        }

        drivedataService.endDriveData(tr_ids,userId);

        for (Trajectory traj:tlist) {
            traj.setCombine(1);
            traj.setEndTime(new DateTime());
            trajectoryService.updateById(traj);


        }


        try{
            for (Trajectory traj:tlist) {
                String startpoint = traj.getStartPoint();
                String endpoint = traj.getEndPoint();

                Double sslo = Double.parseDouble(startpoint.split(",")[0]);
                Double ssla = Double.parseDouble(startpoint.split(",")[1]);


                Double eelo = Double.parseDouble(endpoint.split(",")[0]);
                Double eela = Double.parseDouble(endpoint.split(",")[1]);


                //1°大约111km,0.01=1.11km
                Double sstep = 0.0005;
                Double estep = 0.0005;

                String ak = baidumapUtil.getAk();
                Map<String,Object> params = new HashMap<String,Object>();
                Map<String,Object> parame = new HashMap<String,Object>();
                params.put("ak", ak);
                parame.put("ak", ak);

                Boolean flag=true;

                String saddress;
                JSONObject json;
                JSONObject pois;
                String startaddress="";

                while (flag){
                    params.put("location", ssla.toString()+","+sslo.toString());
                    saddress = baidumapService.getAddress(params);
                    json = JSON.parseObject(saddress);
                    pois = json.getJSONObject("result");
                    startaddress = pois.getString("sematic_description");

                    if(startaddress ==null || startaddress=="" || startaddress.isEmpty()){
                        flag=true;
                        sstep =sstep*-2;
                        sslo = sslo +sstep;
                        ssla = ssla +sstep;
                    }else{
                        flag=false;
                    }
                }
                flag=true;

                String eaddress;
                JSONObject ejson;
                String endaddress="";
                while (flag){
                    parame.put("location", eela.toString()+","+eelo.toString());
                    eaddress = baidumapService.getAddress(parame);
                    ejson = JSON.parseObject(eaddress).getJSONObject("result");
                    pois = ejson.getJSONObject("result");
                    endaddress = ejson.getString("sematic_description");
                    System.out.println(ejson);
                    if(endaddress ==null || endaddress=="" || endaddress.isEmpty()){
                    flag=true;
                    estep =estep*-2;
                    eelo = eelo +estep;
                    eela = eela +estep;
                }else{
                    flag=false;
                }
            }

                traj.setStartPoint(startaddress);
                traj.setEndPoint(endaddress);

                trajectoryService.updateById(traj);
            }

        }catch (NullPointerException e){
            ApiResponse.ofStatus(Status.COMMON_ERROR,"已结束轨迹，但坐标点无法解析");
        };


        return ApiResponse.ofStatus(Status.OK);

    }

    /**
     * 分页查询
     */
    @ApiOperation(value = "【分页查询指定用户的轨迹列表】")
    @GetMapping("/{userId}")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    public ApiResponse queryAllData(@PathVariable Long userId,
                                    @RequestParam(defaultValue = "1") Integer currentPage,
                                    @RequestParam(defaultValue = "10") Integer pageSize,
                                    @RequestParam Map<String, Object> param) {

        QueryResult result = trajectoryService.queryList(userId, currentPage, pageSize, param);
        return ApiResponse.ofStatus(Status.OK, result);

//        if (param.get("sTime") == null && param.get("eTime") == null) {
//            QueryResult result = trajectoryService.queryList(userId, currentPage, pageSize);
//            return ApiResponse.ofStatus(Status.OK, result);
//        }else {
//            QueryResult result = trajectoryService.queryList(userId, currentPage, pageSize, param);
//            return ApiResponse.ofStatus(Status.OK, result);
//        }

    }

    /**
     * 分页条件查询
     */
    @ApiOperation(value = "【分页查询指定用户的轨迹列表】")
    @GetMapping("/query/{userId}")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    public ApiResponse querySomeData(@PathVariable Long userId,
                                    @RequestParam(defaultValue = "1") Integer currentPage,
                                    @RequestParam(defaultValue = "10") Integer pageSize,
                                     @RequestParam Map<String, Object> param) {
        QueryResult result = trajectoryService.queryList(userId, currentPage, pageSize, param);
        return ApiResponse.ofStatus(Status.OK, result);
    }

    /**
     * 添加批注
     */
    @ApiOperation(value = "【轨迹添加批注】")
    @PostMapping("/comment/add")
    public ApiResponse addComment(@RequestBody Map<String, Object> param) {
        Long id = Long.parseLong(param.get("id").toString());
        String comment = param.get("comment").toString();
        Integer result = trajectoryService.addComment(id, comment);
        if (result > 0) {
            return ApiResponse.ofStatus(Status.OK);
        }
        return ApiResponse.ofStatus(Status.COMMON_ERROR);
    }

    /**
     * 获取批注
     */
    @ApiOperation(value = "获取轨迹评注")
    @GetMapping("/comment/{id}")
    public ApiResponse getComment(@PathVariable Long id) {
        return ApiResponse.ofStatus(Status.OK, trajectoryService.getComment(id));
    }

    /**
     * 最近三条轨迹
     */
    @ApiOperation(value = "【轨迹】", notes = "3条历史轨迹")
    @ApiImplicitParam(paramType = "path", dataType = "Integer", name = "userId", value = "用户id", required = true)
    @GetMapping("/lastest/{userId}")
    public ApiResponse fiveTrajectory(@PathVariable Long userId) {

        QueryWrapper<Trajectory> wrapper = new QueryWrapper<>();
        List<Trajectory> trajectorys= trajectoryService.list(wrapper.eq("user_id",userId).orderByDesc("start_time"));

        if (trajectorys.isEmpty()) {
            return ApiResponse.ofStatus(Status.OK,0);
        }else {
            List<String> trajectoryResults = new ArrayList<>();
            for (Trajectory tr: trajectorys) {

                QueryWrapper<Drivedata> drivewrapper = new QueryWrapper<>();
                Drivedata drive = drivedataService.getOne(drivewrapper.eq("trail_id",tr.getId()));

                if (drive.getMileage()<1.0)continue;

                String temp = tr.getPoints();
                trajectoryResults.add(temp);

                if(trajectoryResults.size()==3)break;

            }

            if(trajectoryResults.size()==0)return ApiResponse.ofStatus(Status.OK,0);

            return ApiResponse.ofStatus(Status.OK, trajectoryResults);
        }
    }

}
